home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hottest 6
/
Hottest 6 (1996)(PDSoft)[!].iso
/
software
/
emulators
/
frodo_1.5
/
src
/
1541.asm
next >
Wrap
Assembly Source File
|
1978-11-24
|
35KB
|
1,755 lines
*
* 1541.asm - 1541-Emulation, Dateihandling
*
* Copyright (C) 1994-1995 by Christian Bauer
*
*
* Anmerkungen:
* ------------
*
* Aufrufkonventionen:
* - Die Routinen IECOut#? und IECIn geben in d0 den Status zurück.
* Dieser wird von den aufrufenden Routinen mit dem C64-Statusbyte
* ($90) verodert.
* - Die Routinen dürfen nur d0-d1/a0-a1 verändern
*
* Funktionsweise:
* - Am IEC-Bus gibt es drei Sorten von Geräten: Controller, Listener
* und Talker. Der Controller sind immer wir, zusätzlich können wir
* wahlweise Talker und Listener sein. Es kann immer nur einen Talker
* und einen Listener geben (am echten IEC-Bus sind mehrere Listener
* erlaubt, aber hier nicht).
* - Die Geräte, die angesprochen werden, sind entweder real am IEC-Kabel
* oder werden hier emuliert. Für jedes emulierte Laufwerk existiert
* eine eigene Datenstruktur (Drv?Data). Ein Zeiger darauf wird bei
* Talk/Listen in TalkerData/ListenerData gespeichert und steht den
* nachfolgend aufgerufenen Routinen zur Verfügung, damit sich diese
* um das jeweils angesprochene Laufwerk kümmern.
* - Bei Geräten am Kabel wird #?Data nicht benutzt, da die Routinen
* dann die Daten im wesentlichen einfach an den IEC-Bus durchreichen
*
* EOI/EOF:
* - Im Gegensatz zum Amiga, wo der EOF-Zustand erst nach dem Lesen
* des letzten Bytes erkannt wird, wird beim IEC-Bus das EOF
* gleichzeitig mit dem letzten Byte gesendet. Daher verwenden die
* Leseroutinen einen Puffer, in dem immer ein Byte bereitsteht.
*
* Directory-Emulation:
* - Wird das Directory geöffnet (Dateiname "$"), wird in T: eine
* temporäre Datei angelegt, die vom Aufbau genau einem 1541-Directory
* entspricht und diese Datei geöffnet. Sie kann dann mit den ganz
* normalen Lesebefehlen verarbeitet werden.
*
* Inkompatibilitäten/Verbesserungen:
* - Es kann nur ein Listener gleichzeitig aktiv sein
* - Kein Kommandokanal implementiert
* - Beim Empfang des Dateinamens sollte er auf Pufferüberlauf prüfen
*
MACHINE 68020
INCLUDE "exec/types.i"
INCLUDE "exec/macros.i"
INCLUDE "dos/dos.i"
INCLUDE "dos/dosasl.i"
INCLUDE "resources/misc.i"
INCLUDE "hardware/cia.i"
XREF _SysBase
XREF _DOSBase
XREF _CiaBase
XREF _MiscBase
XREF _ciaaprb
XREF _ciaaddrb
XDEF Open1541
XDEF Close1541
XDEF ChangedDirs
XDEF CloseIEC
XDEF ChangedIEC
XDEF IECOut
XDEF IECOutATN
XDEF IECOutSec
XDEF IECIn
XDEF IECSetATN
XDEF IECRelATN
XDEF IECTurnaround
XDEF IECRelease
XDEF IECIsOpen
XDEF Dir8 ;Prefs
XDEF Dir9
XDEF Dir10
XDEF Dir11
XDEF Drv8IsIEC
XDEF Drv9IsIEC
XDEF Drv10IsIEC
XDEF Drv11IsIEC
XDEF OtherIEC
XDEF MapSlash
SECTION "CODE",CODE
**
** Definitionen
**
; Datenstruktur für ein Laufwerk
STRUCTURE DRVDATA,0
BYTE drv_ErrorCode ;Letzter Fehlercode (ERR_#?)
BYTE drv_ReadBuf ;Byte-Puffer zum Lesen aus Dateien
BYTE drv_IsIEC ;Laufwerk wird über IEC-Kabel angesprochen
BYTE pad0
STRUCT drv_Handles,16*4 ;FileHandles für alle 16 Sekundäradressen
APTR drv_NamePtr ;Zeiger in Dateinamen, für Open/IECOut
APTR drv_ErrorPtr ;Zeiger in Fehlermeldung
APTR drv_Lock ;Lock des Verzeichnisses des Laufwerks
LABEL drv_SIZEOF
; Register (müssen mit den Definitionen in 6510.asm übereinstimmen!)
RAMPTR EQUR a4 ;Zeiger auf C64-RAM
; C64-Status-Codes
ST_OK = 0 ;Alles klar
ST_READ_TIMEOUT = $02 ;Timeout beim Lesen
ST_TIMEOUT = $03 ;Timeout
ST_EOF = $40 ;End of file
ST_NOTPRESENT = $80 ;Device not present
; IEC-Befehlscodes
CMD_DATA = $60
CMD_CLOSE = $e0
CMD_OPEN = $f0
; Fehlercodes (genauer: Die Nummer des zugeh. Fehlertextes)
ERR_OK = 0 ;00: OK
ERR_STARTUP = 1 ;Einschaltmeldung
ERR_FILENOTFOUND = 2 ;62: FILE NOT FOUND
ERR_NOCHANNEL = 3 ;70: NO CHANNEL
ERR_SYNTAX33 = 4 ;33: SYNTAX ERROR (Wildcards beim Schreiben)
; Makros für IEC-Kabel
DATA_HI MACRO
bclr #5,_ciaaprb
ENDM
DATA_LO MACRO
bset #5,_ciaaprb
ENDM
CLOCK_HI MACRO
bclr #4,_ciaaprb
ENDM
CLOCK_LO MACRO
bset #4,_ciaaprb
ENDM
ATN_HI MACRO
bclr #3,_ciaaprb
ENDM
ATN_LO MACRO
bset #3,_ciaaprb
ENDM
LINE_RELEASE MACRO
ATN_HI
bsr Wait40us
CLOCK_HI
DATA_HI
ENDM
; Data -> Carry, Clock -> Negative
GET_DATA_CLOCK MACRO
\@1$ move.b _ciaaprb,d0
cmp.b _ciaaprb,d0
bne \@1$
add.b d0,d0
ENDM
WAIT_CLOCK_HI MACRO
\@1$ GET_DATA_CLOCK
bpl \@1$
ENDM
WAIT_CLOCK_LO MACRO
\@1$ GET_DATA_CLOCK
bmi \@1$
ENDM
WAIT_DATA_HI MACRO
\@1$ GET_DATA_CLOCK
bcc \@1$
ENDM
WAIT_DATA_LO MACRO
\@1$ GET_DATA_CLOCK
bcs \@1$
ENDM
**
** 1541-Emulation starten
**
; Einschaltmeldung bereitstellen
Open1541 move.b #ERR_STARTUP,Drv8Data+drv_ErrorCode
move.b #ERR_STARTUP,Drv9Data+drv_ErrorCode
move.b #ERR_STARTUP,Drv10Data+drv_ErrorCode
move.b #ERR_STARTUP,Drv11Data+drv_ErrorCode
; Locks der Verzeichnisse holen
move.l _DOSBase,a6
bra OpenLocks
**
** 1541-Emulation beenden
**
; Alle Dateien schließen
Close1541 move.l _DOSBase,a6
lea Drv8Data+drv_Handles,a2
bsr FreeHandles
lea Drv9Data+drv_Handles,a2
bsr FreeHandles
lea Drv10Data+drv_Handles,a2
bsr FreeHandles
lea Drv11Data+drv_Handles,a2
bsr FreeHandles
; Alle Locks freigeben
bsr FreeLocks
; Temporäre Datei löschen
move.l #TempFileName,d1
JMPLIB DeleteFile
FreeHandles moveq #15,d7 ;16 Kanäle
2$ move.l (a2)+,d1
beq 1$
clr.l -4(a2) ;FileHandle löschen
JSRLIB Close
1$ dbra d7,2$
rts
**
** Die Verzeichnisse haben sich geändert: Neue Locks holen
**
ChangedDirs move.l _DOSBase,a6
bsr FreeLocks
bra OpenLocks
**
** IEC-Einstellungen wurden verändert
** Rückgabe: d0=0 Alles OK
** d0=1 Parallelport belegt
** d0=2 Kein Timer frei
**
; Einstellungen übertragen
ChangedIEC moveq #0,d1
move.w Drv8IsIEC,d0
or.b d0,d1
move.b d0,Drv8Data+drv_IsIEC
move.w Drv9IsIEC,d0
or.b d0,d1
move.b d0,Drv9Data+drv_IsIEC
move.w Drv10IsIEC,d0
or.b d0,d1
move.b d0,Drv10Data+drv_IsIEC
move.w Drv11IsIEC,d0
or.b d0,d1
move.b d0,Drv11Data+drv_IsIEC
or.w OtherIEC,d1
; IEC öffnen, wenn mindestens ein Gerät mit IEC laufen soll,
; sonst schließen
tst.b d1
beq CloseIEC
bra OpenIEC
**
** Auf Benutzung des IEC-Kabels vorbereiten
** Rückgabe: d0=0 Alles OK
** d0=1 Parallelport belegt
** d0=2 Kein Timer frei
**
OpenIEC move.l a6,-(sp)
tst.b IECIsOpen ;Kann auch mehrmals aufgerufen werden
bne OIECOK
; Parallelport belegen
move.l _MiscBase,a6
moveq #MR_PARALLELPORT,d0
lea ParPortName,a1
JSRLIB AllocMiscResource
tst.l d0
bne OIECNoPort
move.b #$00,_ciaaprb ;Port inaktiv
move.b #$38,_ciaaddrb ;DDR konfigurieren
; Timer A belegen
move.l _CiaBase,a6
lea TimerInterrupt,a1
moveq #CIAICRB_TA,d0
JSRLIB AddICRVector
tst.l d0
bne 1$
; Gelungen
move.b #CIAICRB_TA,WhichTimer
move.b #CIAICRF_TA,WhichTimerMask
move.l #$bfe401,CiaTimerReg
move.l #$bfee01,CiaControlReg
bra 3$
; Nicht gelungen, dann Timer B probieren
1$ lea TimerInterrupt,a1
moveq #CIAICRB_TB,d0
JSRLIB AddICRVector
tst.l d0
bne 2$
; Gelungen
move.b #CIAICRB_TB,WhichTimer
move.b #CIAICRF_TB,WhichTimerMask
move.l #$bfe601,CiaTimerReg
move.l #$bfef01,CiaControlReg
bra 3$
; Nicht gelungen, dann Parallelport wieder freigeben
2$ move.b #$00,_ciaaddrb ;Port auf Eingabe
move.l _MiscBase,a6
moveq #MR_PARALLELPORT,d0
JSRLIB FreeMiscResource
moveq #2,d0 ;Kein Timer frei
move.l (sp)+,a6
rts
; Alles klar, Timer-Interrupt abschalten und Timer stoppen
3$ move.b WhichTimerMask,d0
JSRLIB AbleICR
move.l CiaControlReg,a0
and.b #$80,(a0)
st.b IECIsOpen
OIECOK moveq #0,d0 ;Alles OK
move.l (sp)+,a6
rts
OIECNoPort moveq #1,d0 ;Parallelport belegt
move.l (sp)+,a6
rts
**
** Benutzung des IEC-Kabels beenden
** Rückgabe: d0=0
**
CloseIEC tst.b IECIsOpen
beq 1$
move.b #$00,_ciaaddrb ;Port auf Eingabe
move.l a6,-(sp) ;Parallelport freigeben
move.l _MiscBase,a6
moveq #MR_PARALLELPORT,d0
JSRLIB FreeMiscResource
move.l CiaControlReg,a0 ;Timer stoppen
and.b #$80,(a0)
move.l _CiaBase,a6
lea TimerInterrupt,a1
move.b WhichTimer,d0
JSRLIB RemICRVector
move.l (sp)+,a6
clr.b IECIsOpen
1$ moveq #0,d0
rts
*
* Locks freigeben
*
FreeLocks move.l Drv8Data+drv_Lock,d1
beq 1$
JSRLIB UnLock
1$ move.l Drv9Data+drv_Lock,d1
beq 2$
JSRLIB UnLock
2$ move.l Drv10Data+drv_Lock,d1
beq 3$
JSRLIB UnLock
3$ move.l Drv11Data+drv_Lock,d1
beq 4$
JSRLIB UnLock
4$ rts
*
* Locks holen
*
OpenLocks move.l #Dir8,d1
move.l #ACCESS_READ,d2
JSRLIB Lock
move.l d0,Drv8Data+drv_Lock
move.l #Dir9,d1
move.l #ACCESS_READ,d2
JSRLIB Lock
move.l d0,Drv9Data+drv_Lock
move.l #Dir10,d1
move.l #ACCESS_READ,d2
JSRLIB Lock
move.l d0,Drv10Data+drv_Lock
move.l #Dir11,d1
move.l #ACCESS_READ,d2
JSRLIB Lock
move.l d0,Drv11Data+drv_Lock
rts
**
** IECOut - Ein Byte ausgeben
** d0.b: Byte
** d1.b: <0: EOI-Flag
**
IECOut tst.b ListenerIsIEC ;Listener am IEC-Kabel?
bne IECByteOut ;Ja, dann Byte über Kabel senden
tst.b ListenerActive ;Wurde ein Gerät angesprochen?
beq 1$
cmp.b #CMD_OPEN,ReceivedCmd
beq OpenOut
cmp.b #CMD_DATA,ReceivedCmd
beq DataOut
1$ move.b #ST_TIMEOUT,d0 ;Kein Listener aktiv oder kein gültiger Befehl
rts
**
** IECOutATN - Ein Byte mit ATN ausgeben (Talk/Listen/Untalk/Unlisten)
** d0.b: Byte
**
IECOutATN clr.b SecAddr ;Befehl kommt mit der Sekundäradresse danach
clr.b ReceivedCmd
move.b d0,d1
and.b #$0f,d0 ;d0.b: Gerätenummer
and.b #$f0,d1 ;d1.b: Funktion
st.b Listening ;Funktion auswerten
cmp.b #$20,d1 ;Bei Listen ist das Flag Listening gesetzt
beq Listen
clr.b Listening
cmp.b #$30,d1
beq Unlisten
cmp.b #$40,d1
beq Talk
cmp.b #$50,d1
beq Untalk
move.b #ST_TIMEOUT,d0 ;Ungültige Funktion
rts
**
** IECOutSec - Sekundäradresse ausgeben
** d0.b: Sekundäradresse
**
IECOutSec tst.b Listening ;Nach Listen oder nach Talk?
beq 1$
tst.b ListenerIsIEC ;Nach Listen: Listener am IEC-Kabel?
bne IECByteOutSec
tst.b ListenerActive ;Wurde ein Gerät angesprochen?
beq 2$
move.b d0,d1
and.b #$0f,d0 ;Sekundäradresse
move.b d0,SecAddr
and.b #$f0,d1 ;und Befehlscode speichern
move.b d1,ReceivedCmd
bra SecListen ;Sek.adr nach Listen
1$ tst.b TalkerIsIEC ;Nach Talk: Talker am IEC-Kabel?
bne IECByteOutSec
tst.b TalkerActive ;Wurde ein Gerät angesprochen?
beq 2$
move.b d0,d1
and.b #$0f,d0 ;Sekundäradresse
move.b d0,SecAddr
and.b #$f0,d1 ;und Befehlscode speichern
move.b d1,ReceivedCmd
bra SecTalk ;Sek.adr nach Talk
2$ move.b #ST_TIMEOUT,d0 ;Es erfolgte kein Listen/Talk
rts
**
** IECIn - Ein Byte einlesen
** RÜckgabe: d1.b: Byte
**
IECIn tst.b TalkerIsIEC ;Talker am IEC-Kabel?
bne IECByteIn
tst.b TalkerActive ;Wurde ein Gerät angesprochen?
beq 1$
cmp.b #CMD_DATA,ReceivedCmd
beq DataIn
1$ move.b #ST_TIMEOUT,d0 ;Kein Talk bzw. kein CMD_DATA
clr.b d1
rts
**
** IECSetATN - ATN setzen (für Untalk)
**
IECSetATN tst.b TalkerIsIEC ;Nur bei IEC-Geräten etwas machen
beq 1$
CLOCK_LO
ATN_LO
1$ rts
**
** IECRelATN - ATN wegnehmen
**
IECRelATN tst.b IECIsOpen
beq 1$
ATN_HI
bsr Wait20us
1$ rts
**
** IECTurnaround - Talk-attention turn around
**
IECTurnaround tst.b TalkerIsIEC ;Nur bei IEC-Geräten etwas machen
beq 1$
move.l a6,-(sp)
move.l _SysBase,a6
JSRLIB Disable
DATA_LO
bsr Wait20us
ATN_HI
CLOCK_HI
WAIT_CLOCK_LO
bsr Wait60us
JSRLIB Enable
move.l (sp)+,a6
1$ rts
**
** IECRelease - System line release
**
IECRelease tst.b IECIsOpen
beq 1$
LINE_RELEASE
1$ rts
*
* Listen
* d0.b: Gerätenummer
* d1.b: Funktion
*
Listen cmp.b #8,d0 ;Gerät zwischen 8 und 11?
blo ListenOther
cmp.b #11,d0
bhi ListenOther
moveq #0,d1 ;Ja, Zeiger auf Datenbereich holen
move.b d0,d1
subq.b #8,d1
move.l (DrvTab,d1.w*4),a0
tst.b drv_IsIEC(a0) ;IEC-Gerät?
bne ListenIEC
tst.l drv_Lock(a0) ;Nein, Verzeichnis vorhanden?
beq ListenNotPr
move.l a0,ListenerData ;Ja, Zeiger auf Datenbereich sichern
st.b ListenerActive ;Listener ist aktiv
clr.b ListenerIsIEC
moveq #ST_OK,d0
rts
; Anderes Gerät außer 8..11
ListenOther tst.w OtherIEC
beq ListenNotPr
; Listen über IEC-Kabel
ListenIEC move.l a0,ListenerData ;Zeiger auf Datenbereich sichern
moveq #$20,d1 ;Listen über Kabel senden
bsr IECByteOutATN
cmp.b #ST_NOTPRESENT,d0
beq ListenNotPr
st.b ListenerIsIEC ;Gelungen, Listener ist aktiv
rts
; Gerät nicht vorhanden
ListenNotPr move.b #ST_NOTPRESENT,d0
clr.b ListenerActive
clr.b ListenerIsIEC
rts
*
* Talk
* d0.b: Gerätenummer
* d1.b: Funktion
*
Talk cmp.b #8,d0 ;Gerät zwischen 8 und 11?
blo TalkOther
cmp.b #11,d0
bhi TalkOther
moveq #0,d1 ;Ja, Zeiger auf Datenbereich holen
move.b d0,d1
subq.b #8,d1
move.l (DrvTab,d1.w*4),a0
tst.b drv_IsIEC(a0) ;IEC-Gerät?
bne TalkIEC
tst.l drv_Lock(a0) ;Nein, Verzeichnis vorhanden?
beq TalkNotPr
move.l a0,TalkerData ;Ja, Zeiger auf Datenbereich sichern
st.b TalkerActive ;Talker ist aktiv
clr.b TalkerIsIEC
moveq #ST_OK,d0
rts
; Anderes Gerät außer 8..11
TalkOther tst.w OtherIEC
beq TalkNotPr
; Talk über IEC-Kabel
TalkIEC move.l a0,TalkerData ;Zeiger auf Datenbereich sichern
moveq #$40,d1 ;Talk über Kabel senden
bsr IECByteOutATN
cmp.b #ST_NOTPRESENT,d0
beq TalkNotPr
st.b TalkerIsIEC ;Gelungen, Talker ist aktiv
rts
; Gerät nicht vorhanden
TalkNotPr move.b #ST_NOTPRESENT,d0
clr.b TalkerActive
clr.b TalkerIsIEC
rts
*
* Unlisten
* d0.b: Gerätenummer
* d1.b: Funktion
*
Unlisten tst.b ListenerIsIEC ;Listener am IEC-Kabel?
beq 1$
bsr IECByteOutATN ;Ja, Unlisten über Kabel senden
bra 2$
1$ moveq #ST_OK,d0
2$ clr.b ListenerActive ;Gerät nicht mehr aktiv
clr.b ListenerIsIEC
rts
*
* Untalk
* d0.b: Gerätenummer
* d1.b: Funktion
*
Untalk tst.b TalkerIsIEC ;Talker am IEC-Kabel?
beq 1$
bsr IECByteOutATN ;Ja, Untalk über Kabel senden
bra 2$
1$ moveq #ST_OK,d0
2$ clr.b TalkerActive ;Gerät nicht mehr aktiv
clr.b TalkerIsIEC
rts
*
* SecListen - Sekundäradresse nach Listen
* d0.b: Sekundäradresse
* d1.b: Befehlscode
*
SecListen cmp.b #CMD_OPEN,d1
beq SecListenOpen
cmp.b #CMD_CLOSE,d1
beq SecListenClose
moveq #ST_OK,d0
rts
*
* Open-Befehl: Auf Empfang des Dateinamens vorbereiten
*
SecListenOpen move.l ListenerData,a0
move.l #NameBuf,drv_NamePtr(a0)
moveq #ST_OK,d0
rts
*
* Close-Befehl: Datei schließen
*
SecListenClose movem.l a2/a4/a6,-(sp)
move.l _DOSBase,a6
move.l ListenerData,a4
moveq #0,d0 ;Zeiger auf FileHandle holen
move.b SecAddr,d0
lea drv_Handles(a4,d0.w*4),a2
move.l (a2),d1 ;Datei schließen, wenn geöffnet
beq 1$
JSRLIB Close
clr.l (a2)
1$ movem.l (sp)+,a2/a4/a6
moveq #ST_OK,d0
rts
*
* SecTalk - Sekundäradresse nach Talk
* d0.b: Sekundäradresse
* d1.b: Befehlscode
*
SecTalk cmp.b #15,d0 ;Kanal 15 (Fehlerkanal)?
beq SecTalk15
moveq #ST_OK,d0
rts
*
* Kanal 15: Fehlermeldung bereitstellen
*
SecTalk15 move.l TalkerData,a1
lea ErrorTab,a0 ;Zeiger auf Fehlermeldung laden
moveq #0,d0
move.b drv_ErrorCode(a1),d0
move.l (a0,d0.w*4),drv_ErrorPtr(a1)
move.b #ERR_OK,drv_ErrorCode(a1) ;Fehlercode löschen
moveq #ST_OK,d0
rts
*
* Byte nach Open-Befehl: Zeichen im Dateinamen speichern, bei EOI Datei öffnen
* d0.b: Byte
* d1.b: EOI-Flag
*
OpenOut cmp.b #15,SecAddr ;Kanal 15 (Kommandokanal)?
beq 1$
move.l ListenerData,a0 ;Nein, Zeichen speichern
move.l drv_NamePtr(a0),a1
bsr ConvFrom64 ;Zeichensatz wandeln
move.b d0,(a1)+
move.l a1,drv_NamePtr(a0)
tst.b d1 ;EOI: Datei öffnen
bmi OpenFile
1$ moveq #ST_OK,d0
rts
*
* Dateiname nach Open-Befehl empfangen: Datei öffnen
*
OpenFile movem.l d2-d4/a2/a4/a6,-(sp)
move.l _DOSBase,a6
move.l ListenerData,a4
; Zeiger auf FileHandle nach a2 holen
moveq #0,d0
move.b SecAddr,d0
lea drv_Handles(a4,d0.w*4),a2
; Vorige Datei schließen, wenn noch offen
move.l (a2),d1
beq 1$
JSRLIB Close
clr.l (a2)
1$
; Erstes Zeichen des Dateinamens='$'? Dann Directory öffnen
cmp.b #'$',NameBuf
beq OpenDir
; Erstes Zeichen des Dateinamens='#'? Dann "NO CHANNEL"
cmp.b #'#',NameBuf
beq OpenDirect
; In das Verzeichnis des Laufwerks wechseln
move.l drv_Lock(a4),d1
JSRLIB CurrentDir
move.l d0,d4 ;d4: Lock auf altes Verzeichnis
; Dateinamen mit Nullbyte abschließen, Laufwerksbezeichnung entfernen
; und Dateityp ermitteln
move.l #MODE_OLDFILE,FileMode ;Vorgaben
clr.w FileIsSeq
clr.w FileAppending
move.l drv_NamePtr(a4),a0
clr.b (a0)
lea NameBuf,a0 ;Zuerst nach ':' suchen
move.l a0,FileNamePtr
OFColonLoop tst.b (a0) ;Ende erreicht?
beq OFNoColon
cmp.b #':',(a0)+ ;Nein, ':' gefunden?
bne OFColonLoop ;Nein, weitersuchen
move.l a0,FileNamePtr ;Ja, alles davor abschneiden
OFNoColon move.l FileNamePtr,a0 ;Dann nach ',' suchen
OFCommaLoop1 tst.b (a0) ;Ende erreicht?
beq OFNoComma
cmp.b #',',(a0)+ ;Nein, ',' gefunden?
bne OFCommaLoop1
clr.b -1(a0) ;Ja, alles danach und inklusive abschneiden
move.b (a0)+,d0 ;Dateityp lesen
cmp.b #'s',d0 ;Sequentielle Datei?
bne OFCommaLoop2
move.w #-1,FileIsSeq ;Ja, Flag setzen
OFCommaLoop2 tst.b (a0) ;Ende erreicht?
beq OFNoComma
cmp.b #',',(a0)+ ;Nein, ',' gefunden?
bne OFCommaLoop2
cmp.b #'w',(a0) ;Datei zum Schreiben öffnen?
bne 1$
move.l #MODE_NEWFILE,FileMode
1$ cmp.b #'r',(a0) ;Datei zum Lesen öffnen?
bne 2$
move.l #MODE_OLDFILE,FileMode
2$ cmp.b #'a',(a0) ;Datei zum Anhängen öffnen?
bne 3$
move.l #MODE_OLDFILE,FileMode
move.w #-1,FileAppending ;Ja, Flag setzen
3$
OFNoComma
; Bei Sek.adr 0 immer lesen, bei Sek.adr 1 immer schreiben
cmp.b #0,SecAddr ;Load?
bne 1$
move.l #MODE_OLDFILE,FileMode
1$ cmp.b #1,SecAddr ;Save?
bne 2$
move.l #MODE_NEWFILE,FileMode
2$
; Nach Wildcards suchen, '*' durch '#?' ersetzen,
; Name nach NameBuf2 kopieren und Flag für Wildcard setzen
clr.w FileIsWild ;Vorgabe
move.l FileNamePtr,a0
lea NameBuf2,a1
10$ move.b (a0)+,d0
beq 11$
cmp.b #'*',d0
bne 12$
move.w #'#?',(a1)+ ;'*' -> '#?'
move.w #-1,FileIsWild
bra 11$ ;Danach alles abschneiden
12$ cmp.b #'?',d0
bne 13$
move.b #'?',(a1)+ ;'?' -> '?'
move.w #-1,FileIsWild
bra 10$ ;Weitersuchen
13$ move.b d0,(a1)+
bra 10$ ;Weitersuchen
11$ clr.b (a1)+
; Eine neue Datei darf nicht mit Wildcards geöffnet werden,
; ansonsten nach der ersten passenden Datei suchen
tst.w FileIsWild
beq 20$
cmp.l #MODE_NEWFILE,FileMode
beq OFSyn33
bsr FindFirstFile
20$
; Datei öffnen und erstes Zeichen lesen, wenn zum Lesen geöffnet
move.b #ERR_OK,drv_ErrorCode(a4) ;Vorgabe: Alles OK
move.l #NameBuf2,d1
move.l FileMode,d2
JSRLIB Open
move.l d0,(a2)
beq OFNotFound
tst.w FileAppending ;Datei zum Anhängen geöffnet?
beq 4$
move.l (a2),d1 ;Ja, ans Ende gehen
moveq #0,d2
move.l #OFFSET_END,d3
JSRLIB Seek
bra OFDone
4$ cmp.l #MODE_NEWFILE,FileMode ;Neue Datei anlegen?
beq 5$
move.l (a2),d1 ;Nein, erstes Zeichen lesen
JSRLIB FGetC
move.b d0,drv_ReadBuf(a4)
bra OFDone
5$ tst.w FileIsSeq ;Ja, bei sequentieller Datei E-Bit löschen
beq 7$
move.l (a2),d1
JSRLIB Close
move.l FileNamePtr,d1
move.l #FIBF_EXECUTE,d2
JSRLIB SetProtection
move.l FileNamePtr,d1
move.l FileMode,d2
JSRLIB Open
move.l d0,(a2)
beq OFNotFound
bra OFDone
7$ move.l (a2),d1 ;Sonst E-Bit setzen
JSRLIB Close
move.l FileNamePtr,d1
moveq #0,d2
JSRLIB SetProtection
move.l FileNamePtr,d1
move.l FileMode,d2
JSRLIB Open
move.l d0,(a2)
beq OFNotFound
; In das ursprüngliche Verzeichnis wechseln
OFDone move.l d4,d1
JSRLIB CurrentDir
movem.l (sp)+,d2-d4/a2/a4/a6
moveq #ST_OK,d0
rts
OFSyn33 move.b #ERR_SYNTAX33,drv_ErrorCode(a4)
bra OFDone
OFNotFound move.b #ERR_FILENOTFOUND,drv_ErrorCode(a4)
bra OFDone
*
* Erste zum Muster passende Datei suchen
* Muster in NameBuf2, Dateiname wird ebenfalls dorthin kopiert
* Wenn das MatchFirst fehlschlägt, wird NameBuf2 nicht geändert
* und versucht, die Datei so zu öffnen
*
FindFirstFile lea TheAnchor,a0
clr.l ap_BreakBits(a0)
clr.l ap_Strlen(a0)
move.l #NameBuf2,$180000
move.l #NameBuf2,d1
move.l #TheAnchor,d2
JSRLIB MatchFirst
tst.l d0
bne 1$ ;Nicht gelungen, NameBuf2 nicht ändern
lea TheAnchor+ap_Info+fib_FileName,a0
lea NameBuf2,a1
moveq #63,d0
2$ move.b (a0)+,(a1)+ ;Sonst Name kopieren
dbeq d0,2$
1$ move.l #TheAnchor,d1
JSRLIB MatchEnd
rts
*
* Directory wird geöffnet, temporäre Datei erstellen
*
; Verzeichnis examinieren
OpenDir move.l drv_Lock(a4),d1
move.l #TheFIB,d2
JSRLIB Examine
tst.l d0
beq ODError
; Gelungen, temp. Datei öffnen
move.l #TempFileName,d1
move.l #MODE_NEWFILE,d2
JSRLIB Open
move.l d0,d4 ;d4: FileHandle der temp. Datei
beq ODError
; Directory-Titel erzeugen und schreiben
lea NameBuf,a0
move.l #$01040101,(a0)+ ;Ladeadresse und Verkettung
clr.w (a0)+ ;Laufwerksnummer (0) als Zeilennummer
move.w #$1222,(a0)+ ;RVS ON und '"'
lea TheFIB+fib_FileName,a1
moveq #15,d1 ;Max. 16 Zeichen Verzeichnisname wandeln
1$ move.b (a1)+,d0
bsr ConvTo64
move.b d0,(a0)+
dbeq d1,1$
bne 2$
subq.w #1,a0 ;Den Rest mit Leerzeichen auffüllen
3$ move.b #' ',(a0)+
dbra d1,3$
2$ move.w #$2220,(a0)+ ;'" '
move.l #'00 2',(a0)+ ;ID und Formatkennzeichen
move.w #$4100,(a0)+ ;Abschließendes Nullbyte
move.l d4,d1 ;Zeile schreiben
move.l #NameBuf,d2
moveq #32,d3
JSRLIB Write
; Schleife für alle Verzeichniseinträge
; Nächsten Eintrag holen
ODLoop move.l drv_Lock(a4),d1
move.l #TheFIB,d2
JSRLIB ExNext
tst.l d0
beq ODLoopEnd
; Directory-Zeile erzeugen und schreiben
lea NameBuf,a0 ;Zeile mit Leerzeichen löschen
moveq #30,d1
20$ move.b #' ',(a0)+
dbra d1,20$
clr.b (a0) ;und mit Nullbyte abschließen
lea NameBuf,a0
move.w #$0101,(a0)+ ;Verkettung
move.l TheFIB+fib_Size,d0 ;Größe in Blocks berechnen
add.l #254,d0
divu.w #254,d0
rol.w #8,d0 ;MSB und LSB vertauschen
move.w d0,(a0)+ ;Als Zeilennummer eintragen
rol.w #8,d0 ;Bytefolge korrigieren
addq.l #1,a0 ;Ein Leerzeichen mindestens
cmp.w #10,d0 ;Kleiner als 10?
bhs 10$
addq.l #1,a0 ;Ja, ein Leerzeichen dazunehmen
10$ cmp.w #100,d0 ;Kleiner als 100?
bhs 11$
addq.l #1,a0 ;Ja, noch ein Leerzeichen dazunehmen
11$ move.b #'"',(a0)+
move.l a0,-(sp)
lea TheFIB+fib_FileName,a1
moveq #15,d1 ;Max. 16 Zeichen Dateiname wandeln
1$ move.b (a1)+,d0
bsr ConvTo64
move.b d0,(a0)+
dbeq d1,1$
bne 2$
subq.w #1,a0 ;Nullbyte überschreiben
2$ move.b #'"',(a0)+ ;Mit '"' abschließen
move.l (sp)+,a0
lea 18(a0),a0 ;An festgelegter Spalte weitermachen
tst.l TheFIB+fib_DirEntryType ;Typ ermitteln und eintragen
bmi ODIsFile
move.l #'DIR ',(a0)+
bra ODLineEnd
ODIsFile btst #FIBB_EXECUTE,TheFIB+fib_Protection+3
beq ODIsPRG
move.l #'SEQ ',(a0)+
bra ODLineEnd
ODIsPRG move.l #'PRG ',(a0)+
ODLineEnd move.l d4,d1 ;Zeile schreiben
move.l #NameBuf,d2
moveq #32,d3
JSRLIB Write
bra ODLoop
; Abschlußzeile mit "BLOCKS FREE." erzeugen und schreiben
ODLoopEnd lea NameBuf,a0 ;Zeile mit Leerzeichen löschen
moveq #28,d1
20$ move.b #' ',(a0)+
dbra d1,20$
clr.w (a0)+ ;Und mit drei Nullbytes abschließen
clr.b (a0)
lea NameBuf,a0
move.w #$0101,(a0)+ ;Verkettung
clr.w (a0)+ ;Anzahl freier Blöcke (0)
move.l #'BLOC',(a0)+
move.l #'KS F',(a0)+
move.l #'REE.',(a0)+
move.l d4,d1 ;Zeile schreiben
move.l #NameBuf,d2
moveq #32,d3
JSRLIB Write
; Temp. Datei schließen
move.l d4,d1
JSRLIB Close
; Und wieder zum Lesen öffnen und das erste Zeichen lesen
move.l #TempFileName,d1
move.l #MODE_OLDFILE,d2
JSRLIB Open
move.l d0,(a2)
beq ODError
move.l d0,d1
JSRLIB FGetC
move.b d0,drv_ReadBuf(a4)
ODError movem.l (sp)+,d2-d4/a2/a4/a6
moveq #ST_OK,d0
rts
*
* Direktzugriffskanal wird geöffnet, Fehlermeldung
*
OpenDirect move.b #ERR_NOCHANNEL,drv_ErrorCode(a4)
movem.l (sp)+,d2-d4/a2/a4/a6
moveq #ST_OK,d0
rts
*
* Byte nach Data-Befehl: Zeichen in Datei schreiben
* d0.b: Byte
* d1.b: EOI-Flag
*
DataOut cmp.b #15,SecAddr ;Kanal 15 (Kommandokanal)?
beq 2$
movem.l d2/a2/a4/a6,-(sp)
move.l _DOSBase,a6
move.l ListenerData,a4
moveq #0,d2
move.b d0,d2 ;d2: Byte
moveq #0,d0 ;Zeiger auf FileHandle holen
move.b SecAddr,d0
lea drv_Handles(a4,d0.w*4),a2
move.l (a2),d1 ;Datei geöffnet?
beq 1$
JSRLIB FPutC ;Zeichen schreiben
tst.l d0
bmi 1$
moveq #ST_OK,d0
movem.l (sp)+,d2/a2/a4/a6
rts
1$ move.b #ST_TIMEOUT,d0 ;Fehler aufgetreten
movem.l (sp)+,d2/a2/a4/a6
rts
2$ moveq #ST_OK,d0
rts
*
* Zeichen aus Datenkanal lesen
* RÜckgabe: d1.b: Byte
*
DataIn cmp.b #15,SecAddr ;Kanal 15 (Fehlerkanal)?
beq Channel15In
movem.l d2/a2/a4/a6,-(sp)
move.l _DOSBase,a6
move.l TalkerData,a4
moveq #0,d0 ;Zeiger auf FileHandle holen
move.b SecAddr,d0
lea drv_Handles(a4,d0.w*4),a2
move.l (a2),d1 ;Datei geöffnet?
beq 1$
move.b drv_ReadBuf(a4),d2 ;Zeichen aus dem Puffer holen
JSRLIB FGetC ;Nächstes Zeichen lesen
move.b d0,drv_ReadBuf(a4) ;und Puffern
tst.l d0
bmi 2$ ;EOF? Dann Status setzen
moveq #ST_OK,d0
bra 3$
2$ move.b #ST_EOF,d0
3$ move.b d2,d1 ;Zeichen wieder holen
movem.l (sp)+,d2/a2/a4/a6
rts
1$ move.b #ST_READ_TIMEOUT,d0 ;Fehler aufgetreten
clr.b d1
movem.l (sp)+,d2/a2/a4/a6
rts
*
* Aus Kanal 15 lesen
*
Channel15In move.l TalkerData,a0
move.l drv_ErrorPtr(a0),a1 ;Nächstes Zeichen holen
move.b (a1)+,d1
cmp.b #13,d1 ;CR (letztes Zeichen)?
beq 1$
move.l a1,drv_ErrorPtr(a0) ;Nein, Zeiger merken
moveq #ST_OK,d0
rts
1$ move.b #ST_EOF,d0 ;Letztes Zeichen: EOF
move.l #OKText,drv_ErrorPtr(a0) ;Falls jemand noch mehr will...
rts
*
* Umwandlung PETSCII->ASCII
* Zeichen in d0
*
ConvFrom64 cmp.b #'/',d0
beq 3$
cmp.b #'A',d0
blo 1$
cmp.b #'Z',d0
bhi 2$
or.b #$20,d0 ;Großbuchstaben
rts
2$ cmp.b #'a',d0
blo 1$
cmp.b #'z',d0
bhi 1$
and.b #$df,d0 ;Kleinbuchstaben
1$ rts
3$ tst.w MapSlash
beq 1$
move.b #'\\',d0
rts
*
* Umwandlung ASCII->PETSCII
* Zeichen in d0
*
ConvTo64 cmp.b #'\\',d0
beq 3$
cmp.b #'A',d0
blo 1$
cmp.b #'Z',d0
bhi 2$
or.b #$20,d0 ;Großbuchstaben
rts
2$ cmp.b #'a',d0
blo 1$
cmp.b #'z',d0
bhi 1$
and.b #$df,d0 ;Kleinbuchstaben
1$ rts
3$ tst.w MapSlash
beq 1$
move.b #'/',d0
rts
*
* Byte mit ATN über IEC-Kabel senden
* d0.b: Gerätenummer
* d1.b: Funktion
*
IECByteOutATN tst.b IECIsOpen
bne 1$
move.b #ST_NOTPRESENT,d0
rts
1$ movem.l d2/d7/a6,-(sp)
move.b d0,d2
or.b d1,d2 ;d2: Auszugebendes Byte
move.l _SysBase,a6
JSRLIB Disable
DATA_HI
ATN_LO
bra IECByteOutSec2 ;ATN response abwarten und Byte ausgeben
*
* Sekundäradresse über IEC-Kabel senden
* d0.b: Sekundäradresse
*
IECByteOutSec tst.b IECIsOpen
bne 1$
move.b #ST_NOTPRESENT,d0
rts
1$ movem.l d2/d7/a6,-(sp)
move.b d0,d2 ;d2: Auszugebendes Byte
move.l _SysBase,a6
JSRLIB Disable
IECByteOutSec2 CLOCK_LO
DATA_HI
bsr Wait1ms ;Max ATN response abwarten
moveq #0,d1 ;Kein EOI
bra IECByteOut2 ;Byte ausgeben
*
* Byte über IEC-Kabel senden
* d0.b: Byte
* d1.b: EOI-Flag
*
IECByteOut tst.b IECIsOpen
bne 1$
move.b #ST_NOTPRESENT,d0
rts
1$ movem.l d2/d7/a6,-(sp)
move.b d0,d2 ;d2: Auszugebendes Byte
move.l _SysBase,a6
JSRLIB Disable
; Übertragung einleiten
IECByteOut2 move.b d1,d7 ;d7: EOI-Flag
DATA_HI
GET_DATA_CLOCK ;Data bleibt high -> Device not present
bcs IBODevNotPr
CLOCK_HI ;Talker ready
WAIT_DATA_HI ;Warten auf Listener ready for data
tst.b d7 ;EOI?
bpl 1$
WAIT_DATA_LO ;Ja, EOI-Handshake abwarten
WAIT_DATA_HI
1$ CLOCK_LO ;Talker sending
bsr Wait40us ;Wichtige Verzögerung, aber wozu?
; 8 Bits übertragen
moveq #7,d7 ;d7: Bitzähler
IBOBitLoop GET_DATA_CLOCK ;Data low -> Time out
bcc IBOTimeOut
lsr.b #1,d2 ;Nächstes Bit holen
bcc 1$ ;und ausgeben
DATA_HI
bra 2$
1$ DATA_LO
2$
bsr Wait40us ;Bit set-up talker delay
CLOCK_HI ;Data valid
bsr Wait20us ;Data valid delay
DATA_HI
CLOCK_LO
dbra d7,IBOBitLoop ;Nächstes Bit
; 1ms auf Bestätigung warten
bsr Start1ms ;Timer starten
IBODACLoop bsr TimerDoneQ ;Timer abgelaufen?
bne IBOTimeOut ;Ja, dann Time out
GET_DATA_CLOCK ;Auf Listener data accepted warten
bcs IBODACLoop
; Alles OK
moveq #ST_OK,d0
bra IBODone
; Fehlerbehandlung
IBODevNotPr LINE_RELEASE
move.b #ST_NOTPRESENT,d0
bra IBODone
IBOTimeOut LINE_RELEASE
move.b #ST_TIMEOUT,d0
IBODone JSRLIB Enable
movem.l (sp)+,a6/d2/d7
rts
*
* Byte über IEC-Kabel empfangen
* Rückgabe: d1.b: Empfangenes Byte
*
IECByteIn tst.b IECIsOpen
bne 1$
move.b #ST_NOTPRESENT,d0
rts
1$ movem.l d2/d3/d7/a6,-(sp)
moveq #ST_OK,d3 ;d3: Status
move.l _SysBase,a6
JSRLIB Disable
CLOCK_HI
WAIT_CLOCK_HI
; Auf Beginn der Übertragung warten
bsr Start250us ;Timer starten
DATA_HI ;Listener ready for data
IBIWaitTalker bsr TimerDoneQ ;Timer abgelaufen?
bne IBIEOI ;Ja, EOI empfangen
GET_DATA_CLOCK ;Warten auf talker sending
bmi IBIWaitTalker
bra IBIReceive
; EOI empfangen, Handshake senden und erneut auf Beginn warten
IBIEOI move.b #ST_EOF,d3
DATA_LO ;EOI handshake
CLOCK_HI
bsr Wait60us ;EOI response hold time
bsr Start250us ;Timer starten
DATA_HI ;Listener ready for data
IBIWaitTalker2 bsr TimerDoneQ ;Timer abgelaufen?
bne IBITimeOut ;Ja, dann Time out
GET_DATA_CLOCK ;Warten auf talker sending
bmi IBIWaitTalker2
; 8 Bits empfangen
IBIReceive moveq #7,d7 ;d7: Bitzähler
moveq #0,d2 ;d2: Empfangenes Byte
IBIBitLoop WAIT_CLOCK_HI ;Auf Data valid warten
roxr.b #1,d2 ;Datenbit holen
WAIT_CLOCK_LO
dbra d7,IBIBitLoop
; Empfang bestätigen
DATA_LO ;Listener data accepted
btst #6,d3 ;EOI empfangen?
beq IBIDone
LINE_RELEASE ;Ja, Leitung freigeben
bra IBIDone
; Fehlerbehandlung
IBITimeOut or.b #ST_READ_TIMEOUT,d3
LINE_RELEASE
IBIDone move.b d3,d0 ;Status holen
move.b d2,d1 ;Byte holen
JSRLIB Enable
movem.l (sp)+,d2/d3/d7/a6
rts
*
* 20µs/40µs/60µs/1ms warten
*
; Timer auf 20µs setzen
Wait20us move.l CiaControlReg,a0
and.b #$80,(a0)
move.l CiaTimerReg,a0
move.b #14,(a0)
move.b #0,$100(a0)
bra StartTimer
; Timer auf 40µs setzen
Wait40us move.l CiaControlReg,a0
and.b #$80,(a0)
move.l CiaTimerReg,a0
move.b #29,(a0)
move.b #0,$100(a0)
bra StartTimer
; Timer auf 60µs setzen
Wait60us move.l CiaControlReg,a0
and.b #$80,(a0)
move.l CiaTimerReg,a0
move.b #43,(a0)
move.b #0,$100(a0)
bra StartTimer
; Timer auf 1ms setzen
Wait1ms move.l CiaControlReg,a0
and.b #$80,(a0)
move.l CiaTimerReg,a0
move.b #$cc,(a0)
move.b #2,$100(a0)
move.l CiaControlReg,a0
; Timer anwerfen (One-Shot) und auf Ablauf warten
StartTimer move.l a6,-(sp)
move.l _CiaBase,a6
move.b WhichTimerMask,d0
JSRLIB SetICR
move.l CiaControlReg,a0
move.b #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
1$ moveq #0,d0
JSRLIB SetICR
and.b WhichTimerMask,d0
beq 1$
move.l (sp)+,a6
rts
*
* Timer starten, 1ms/250µs
*
Start1ms move.l a6,-(sp)
move.l _CiaBase,a6
move.l CiaControlReg,a0
and.b #$80,(a0)
move.l CiaTimerReg,a0
move.b #$cc,(a0)
move.b #2,$100(a0)
move.b WhichTimerMask,d0
JSRLIB SetICR
move.l CiaControlReg,a0
or.b #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
move.l (sp)+,a6
rts
Start250us move.l a6,-(sp)
move.l _CiaBase,a6
move.l CiaControlReg,a0
and.b #$80,(a0)
move.l CiaTimerReg,a0
move.b #$b3,(a0)
move.b #0,$100(a0)
move.b WhichTimerMask,d0
JSRLIB SetICR
move.l CiaControlReg,a0
or.b #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
move.l (sp)+,a6
rts
*
* Timer abgelaufen?
* bne: Ja
*
TimerDoneQ move.l a6,-(sp)
move.l _CiaBase,a6
moveq #0,d0
JSRLIB SetICR
and.b WhichTimerMask,d0
move.l (sp)+,a6
tst.b d0
rts
*
* Dummy-Timer-Interrupt-Routine
*
IntTimer moveq #0,d0
rts
**
** Konstanten
**
; Tabelle für Fehlermeldungen (Index: ErrorCode)
CNOP 0,4
ErrorTab dc.l OKText
dc.l StartupText
dc.l FileNotFText
dc.l NoChannelText
dc.l Syntax33Text
; Fehlertexte
OKText dc.b "00, OK,00,00",13
StartupText dc.b "73,CBM DOS V2.6 1541,00,00",13
FileNotFText dc.b "62,FILE NOT FOUND,00,00",13
NoChannelText dc.b "70,NO CHANNEL,00,00",13
Syntax33Text dc.b "33,SYNTAX ERROR,00,00",13
; Tabelle mit Zeigern auf die Laufwerks-Datenstrukturen
CNOP 0,4
DrvTab dc.l Drv8Data
dc.l Drv9Data
dc.l Drv10Data
dc.l Drv11Data
; Name der temporären Datei für das Directory
TempFileName dc.b "T:Frodo$File",0
; Name für AllocMiscResource
ParPortName dc.b "Frodo Parallel Port",0
; Name des Timer-Interrupts
TimerIntName dc.b "Frodo Timer Int",0
CNOP 0,4
**
** Initialisierte Daten
**
SECTION "DATA",DATA
TimerInterrupt dc.l 0,0
dc.b NT_INTERRUPT,0
dc.l TimerIntName
dc.l 0
dc.l IntTimer
**
** Nicht initialisierte Daten
**
SECTION "BSS",BSS
; Global
ListenerActive ds.b 1 ;Flag: Listener angewählt, ListenerData ist gültig
ListenerIsIEC ds.b 1 ;Flag: Aktiver Listener hängt am IEC-Kabel (impliziert ListenerActive)
TalkerActive ds.b 1 ;Flag: Talker angewählt, TalkerData ist gültig
TalkerIsIEC ds.b 1 ;Flag: Aktiver Talker hängt am IEC-Kabel (impliziert TalkerActive)
Listening ds.b 1 ;Flag: Letzter ATN-Befehl war Listen (für SecListen/SecTalk-Unterscheidung)
SecAddr ds.b 1 ;Aktuelle Sekundäradresse ($0x)
ReceivedCmd ds.b 1 ;Empfangener Befehlscode ($x0)
IECIsOpen ds.b 1 ;Flag: Timer und Port belegt, IEC-Kabel kann benutzt werden
WhichTimer ds.b 1 ;Welcher Timer wurde belegt? (0: Timer A, 1: Timer B)
WhichTimerMask ds.b 1 ;Dto. als Bit-Maske für ICR
CNOP 0,4
CiaTimerReg ds.l 1 ;Zeiger auf Cia-Timer-Register
CiaControlReg ds.l 1
ListenerData ds.l 1 ;Zeiger auf Struktur des aktiven Listeners
TalkerData ds.l 1 ;Zeiger auf Struktur des aktiven Talkers
FileNamePtr ds.l 1 ;Zeiger auf Dateinamen für OpenFile
FileMode ds.l 1 ;Zugriffsmodus für OpenFile
FileIsSeq ds.w 1 ;Flag: Sequentielle Datei eröffnen
FileAppending ds.w 1 ;Flag: Daten an Datei anhängen
FileIsWild ds.w 1 ;Flag: Wildcards gefunden
; Datenstruktur pro Laufwerk
CNOP 0,4
Drv8Data ds.b drv_SIZEOF
Drv9Data ds.b drv_SIZEOF
Drv10Data ds.b drv_SIZEOF
Drv11Data ds.b drv_SIZEOF
; Puffer für die Verzeichnisse der 4 Laufwerke
Dir8 ds.b 256
Dir9 ds.b 256
Dir10 ds.b 256
Dir11 ds.b 256
; Puffer für Dateinamen
NameBuf ds.b 64
NameBuf2 ds.b 64
; Struktur für MatchFirst
CNOP 0,4
TheAnchor ds.b ap_SIZEOF
; Einstellungen
Drv8IsIEC ds.w 1
Drv9IsIEC ds.w 1
Drv10IsIEC ds.w 1
Drv11IsIEC ds.w 1
OtherIEC ds.w 1
MapSlash ds.w 1
CNOP 0,4
TheFIB ds.b fib_SIZEOF ;FileInfoBlock
END